From 6e533199b1e5a5e69a1c0579312c6c11ce2d7f62 Mon Sep 17 00:00:00 2001 From: "iap10@labyrinth.cl.cam.ac.uk" Date: Tue, 8 Feb 2005 23:57:18 +0000 Subject: [PATCH] bitkeeper revision 1.1159.1.556 (420951de12d7YPCDmxFldoqZYbe2cw) Subject: [PATCH] pit-in-hv.patch - Use ac_timer for PIT interrupt injection (more accurate time keeping) - Accelerate some critical PIT I/O operations in the hypervisor (saves 15us per op). Cuts down guest timer interrupt handler execution time by a third. - If the domain is scheduled out, make sure that interrupts are not lost - Add a generic framework for device I/O interception Signed-off-by: Edwin Zhai Signed-off-by: Arun Sharma Signed-off-by: ian@xensource.com --- .rootkeys | 3 + tools/ioemu/iodev/cpu.cc | 6 +- tools/ioemu/iodev/pic.cc | 15 ++ tools/ioemu/iodev/pic.h | 2 +- tools/ioemu/iodev/pit82c54.cc | 37 ++++ tools/ioemu/iodev/pit82c54.h | 9 + tools/ioemu/iodev/pit_wrap.cc | 6 + xen/arch/x86/domain.c | 2 + xen/arch/x86/vmx.c | 10 +- xen/arch/x86/vmx_intercept.c | 257 ++++++++++++++++++++++++++++ xen/arch/x86/vmx_io.c | 16 +- xen/include/asm-x86/vmx_intercept.h | 31 ++++ xen/include/asm-x86/vmx_platform.h | 4 + xen/include/asm-x86/vmx_virpit.h | 81 +++++++++ xen/include/public/io/ioreq.h | 1 + 15 files changed, 476 insertions(+), 4 deletions(-) create mode 100644 xen/arch/x86/vmx_intercept.c create mode 100644 xen/include/asm-x86/vmx_intercept.h create mode 100644 xen/include/asm-x86/vmx_virpit.h diff --git a/.rootkeys b/.rootkeys index 97ace4a85e..bb53b189fe 100644 --- a/.rootkeys +++ b/.rootkeys @@ -915,6 +915,7 @@ 3ddb79bccYVzXZJyVaxuv5T42Z1Fsw xen/arch/x86/trampoline.S 3ddb79bcOftONV9h4QCxXOfiT0h91w xen/arch/x86/traps.c 41c0c411tD3C7TpfDMiFTf7BaNd_Dg xen/arch/x86/vmx.c +420951dcf1rSGnCH0AEYN2KjWGLG6A xen/arch/x86/vmx_intercept.c 41c0c411ODt8uEmV-yUxpQLpqimE5Q xen/arch/x86/vmx_io.c 41f97ef5139vN42cOYHfX_Ac8WOOjA xen/arch/x86/vmx_platform.c 41c0c4128URE0dxcO15JME_MuKBPfg xen/arch/x86/vmx_vmcs.c @@ -1057,7 +1058,9 @@ 40cf1596saFaHD5DC5zvrSn7CDCWGQ xen/include/asm-x86/uaccess.h 41c0c412k6GHYF3cJtDdw37ee3TVaw xen/include/asm-x86/vmx.h 41c0c412hck3QX-6_MaXaISGkngQuA xen/include/asm-x86/vmx_cpu.h +420951dcGoqsqnmjjAtEtm6-3dM9KA xen/include/asm-x86/vmx_intercept.h 41c0c41243jC1mcArZx_t3YkBL4lTA xen/include/asm-x86/vmx_platform.h +420951dcqyUCe_gXA_XJPu1ix_poKg xen/include/asm-x86/vmx_virpit.h 41c0c412lQ0NVVN9PsOSznQ-qhOiPA xen/include/asm-x86/vmx_vmcs.h 418fbcfe_WliJPToeVM-9VStvym-hw xen/include/asm-x86/x86_32/asm_defns.h 3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/include/asm-x86/x86_32/current.h diff --git a/tools/ioemu/iodev/cpu.cc b/tools/ioemu/iodev/cpu.cc index 71853afa61..59e4c51c05 100644 --- a/tools/ioemu/iodev/cpu.cc +++ b/tools/ioemu/iodev/cpu.cc @@ -144,7 +144,11 @@ void bx_cpu_c::dispatch_ioreq(ioreq_t *req) } } } - req->state = STATE_IORESP_READY; + + /* No state change if state = STATE_IORESP_HOOK */ + if (req->state == STATE_IOREQ_INPROCESS) + req->state = STATE_IORESP_READY; + send_event = 1; } diff --git a/tools/ioemu/iodev/pic.cc b/tools/ioemu/iodev/pic.cc index d79c376220..f4455508b6 100644 --- a/tools/ioemu/iodev/pic.cc +++ b/tools/ioemu/iodev/pic.cc @@ -855,6 +855,21 @@ bx_pic_c::IAC(void) BX_DBG_IAC_REPORT(vector, irq); return(vector); } + + Bit8u +bx_pic_c::irq_to_vec(Bit8u irq) +{ + Bit8u vector = 0; + + if (irq >= 8 && irq <= 15) + vector = irq + BX_PIC_THIS s.slave_pic.interrupt_offset; + else if (irq != 2 && irq <= 7) + vector = irq + BX_PIC_THIS s.master_pic.interrupt_offset; + else + BX_ERROR(("invalid irq!\n")); + + return vector; +} void bx_pic_c::show_pic_state(void) diff --git a/tools/ioemu/iodev/pic.h b/tools/ioemu/iodev/pic.h index cfdb1263ef..378809d67d 100644 --- a/tools/ioemu/iodev/pic.h +++ b/tools/ioemu/iodev/pic.h @@ -67,7 +67,6 @@ typedef struct { class bx_pic_c : public bx_pic_stub_c { - public: bx_pic_c(void); ~bx_pic_c(void); @@ -77,6 +76,7 @@ public: virtual void raise_irq(unsigned irq_no); virtual Bit8u IAC(void); virtual void show_pic_state(void); + Bit8u irq_to_vec(Bit8u); private: struct { diff --git a/tools/ioemu/iodev/pit82c54.cc b/tools/ioemu/iodev/pit82c54.cc index fc913b1334..493faf6ee1 100644 --- a/tools/ioemu/iodev/pit82c54.cc +++ b/tools/ioemu/iodev/pit82c54.cc @@ -608,6 +608,37 @@ pit_82C54::clock(Bit8u cnum) { return 0; } +#ifdef BX_VMX_PIT +//extra operations when use vmx pit device model + void pit_82C54::write_initcount_vmx(Bit8u cnum) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Counter number incorrect\n")); + } + + ioreq_t *req = &((vcpu_iodata_t *) shared_page)->vp_ioreq; + extern bx_pic_c *thePic; + counter_type & thisctr = counter[cnum]; + if(req->pdata_valid) { + BX_ERROR(("VMX_PIT:err!pit is port io!\n")); + } + + if (thisctr.mode == 2) {//periodic mode, need HV to help send interrupt + req->state = STATE_IORESP_HOOK; + +// req->u.data = thisctr.inlatch * 1000 / PIT_FREQ;//init count:16 bit + req->u.data = thisctr.inlatch; //init count:16 bit + //get the pit irq(0)'s vector from pic DM + req->u.data |= ((thePic->irq_to_vec(0)) << 16 ); //timer vec:8 bit + req->u.data |= (cnum << 24); //PIT channel(0~2):2 bit + req->u.data |= ((thisctr.rw_mode) << 26); //rw mode:2 bit + + BX_INFO(("VMX_PIT:whole pit hook packet = 0x%llx \n", (req->u.data ) )); + BX_INFO(("VMX_PIT:init counter = %d ms\n", (req->u.data & 0xFFFF) )); + } + + } +#endif + void pit_82C54::write(Bit8u address, Bit8u data) { if(address>MAX_ADDRESS) { BX_ERROR(("Counter address incorrect in data write.")); @@ -709,6 +740,9 @@ pit_82C54::clock(Bit8u cnum) { thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data; thisctr.null_count=1; thisctr.count_written=1; +#ifdef BX_VMX_PIT + write_initcount_vmx(address); +#endif break; case MSByte_multiple: thisctr.write_state=LSByte_multiple; @@ -716,6 +750,9 @@ pit_82C54::clock(Bit8u cnum) { thisctr.inlatch=(thisctr.inlatch & 0xFF) | (data<<8); thisctr.null_count=1; thisctr.count_written=1; +#ifdef BX_VMX_PIT + write_initcount_vmx(address); +#endif break; default: BX_ERROR(("write counter in invalid write state.")); diff --git a/tools/ioemu/iodev/pit82c54.h b/tools/ioemu/iodev/pit82c54.h index bae2c2b8ac..95d36b3973 100644 --- a/tools/ioemu/iodev/pit82c54.h +++ b/tools/ioemu/iodev/pit82c54.h @@ -15,6 +15,11 @@ #include "bochs.h" +#ifdef BX_USE_VMX +#define BX_VMX_PIT 1 +#define PIT_FREQ 1193181 +#endif + class pit_82C54 : public logfunctions { @@ -108,6 +113,10 @@ private: void print_counter(counter_type & thisctr); +#ifdef BX_USE_VMX + void write_initcount_vmx(Bit8u cnum); +#endif + public: void init (void); void reset (unsigned type); diff --git a/tools/ioemu/iodev/pit_wrap.cc b/tools/ioemu/iodev/pit_wrap.cc index ae09b3e26b..5fd1721073 100644 --- a/tools/ioemu/iodev/pit_wrap.cc +++ b/tools/ioemu/iodev/pit_wrap.cc @@ -326,11 +326,13 @@ bx_pit_c::write( Bit32u address, Bit32u dvalue, (unsigned) address, (unsigned) value)); } +#ifndef BX_VMX_PIT if ((BX_PIT_THIS s.timer.read_OUT(0))==1) { DEV_pic_raise_irq(0); } else { DEV_pic_lower_irq(0); } +#endif if(time_passed || (BX_PIT_THIS s.last_next_event_time @@ -419,12 +421,16 @@ bx_pit_c::periodic( Bit32u usec_delta ) BX_PIT_THIS s.timer.clock_all(timedelta); if ( (prev_timer0_out==0) ) { if ((BX_PIT_THIS s.timer.read_OUT(0))==1) { +#ifndef BX_VMX_PIT DEV_pic_raise_irq(0); +#endif prev_timer0_out=1; } } else { if ((BX_PIT_THIS s.timer.read_OUT(0))==0) { +#ifndef BX_VMX_PIT DEV_pic_lower_irq(0); +#endif prev_timer0_out=0; } } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index f544b8f29c..b3946df9f2 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -756,6 +756,7 @@ static void relinquish_list(struct domain *d, struct list_head *list) #ifdef CONFIG_VMX static void vmx_domain_relinquish_memory(struct exec_domain *ed) { + struct vmx_virpit_t *vpit = &(ed->arch.arch_vmx.vmx_platform.vmx_pit); /* * Free VMCS */ @@ -764,6 +765,7 @@ static void vmx_domain_relinquish_memory(struct exec_domain *ed) ed->arch.arch_vmx.vmcs = 0; monitor_rm_pagetable(ed); + rem_ac_timer(&(vpit->pit_timer)); } #endif diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index b2dd257969..70e669183f 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #ifdef CONFIG_VMX @@ -359,7 +360,6 @@ static void vmx_io_instruction(struct xen_regs *regs, } p = &vio->vp_ioreq; p->dir = test_bit(3, &exit_qualification); - set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags); p->pdata_valid = 0; p->count = 1; @@ -396,6 +396,14 @@ static void vmx_io_instruction(struct xen_regs *regs, p->addr = addr; p->port_mm = 0; + + /* Check if the packet needs to be intercepted */ + if (vmx_io_intercept(p)) { + /* no blocking & no evtchn notification */ + return; + } + + set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags); p->state = STATE_IOREQ_READY; evtchn_send(IOPACKET_PORT); do_block(); diff --git a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/vmx_intercept.c new file mode 100644 index 0000000000..54cefbe92c --- /dev/null +++ b/xen/arch/x86/vmx_intercept.c @@ -0,0 +1,257 @@ +/* + * vmx_intercept.c: Handle performance critical I/O packets in hypervisor space + * Copyright (c) 2004, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* for intercepting io request after vm_exit, return value: 0--not handle; 1--handled */ +int vmx_io_intercept(ioreq_t *p) +{ + struct exec_domain *d = current; + struct vmx_handler_t *handler = &(d->arch.arch_vmx.vmx_platform.vmx_handler); + int i; + unsigned addr, offset; + for (i = 0; i < handler->num_slot; i++) { + addr = handler->hdl_list[i].addr; + offset = handler->hdl_list[i].offset; + if (p->addr >= addr && + p->addr < addr + offset) + return handler->hdl_list[i].action(p); + } + return 0; +} + +int register_io_handler(unsigned long addr, unsigned long offset, intercept_action_t action) +{ + struct exec_domain *d = current; + struct vmx_handler_t *handler = &(d->arch.arch_vmx.vmx_platform.vmx_handler); + int num = handler->num_slot; + + if (num >= MAX_IO_HANDLER) { + printk("no extra space, register io interceptor failed!\n"); + domain_crash(); + } + + handler->hdl_list[num].addr = addr; + handler->hdl_list[num].offset = offset; + handler->hdl_list[num].action = action; + handler->num_slot++; + return 1; + +} + +static void pit_cal_count(struct vmx_virpit_t *vpit) +{ + unsigned int usec_delta = (unsigned int)((NOW() - vpit->inject_point) / 1000); + if (usec_delta > vpit->period * 1000) + VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:long time has passed from last injection!\n"); + vpit->count = vpit->init_val - ((usec_delta * PIT_FREQ / 1000000) % vpit->init_val ); +} + +static void pit_latch_io(struct vmx_virpit_t *vpit) +{ + pit_cal_count(vpit); + + switch(vpit->read_state) { + case MSByte: + vpit->count_MSB_latched=1; + break; + case LSByte: + vpit->count_LSB_latched=1; + break; + case LSByte_multiple: + vpit->count_LSB_latched=1; + vpit->count_MSB_latched=1; + break; + case MSByte_multiple: + VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:latch PIT counter before MSB_multiple!"); + vpit->read_state=LSByte_multiple; + vpit->count_LSB_latched=1; + vpit->count_MSB_latched=1; + break; + default: + BUG(); + } +} + +static int pit_read_io(struct vmx_virpit_t *vpit) +{ + if(vpit->count_LSB_latched) { + /* Read Least Significant Byte */ + if(vpit->read_state==LSByte_multiple) { + vpit->read_state=MSByte_multiple; + } + vpit->count_LSB_latched=0; + return (vpit->count & 0xFF); + } else if(vpit->count_MSB_latched) { + /* Read Most Significant Byte */ + if(vpit->read_state==MSByte_multiple) { + vpit->read_state=LSByte_multiple; + } + vpit->count_MSB_latched=0; + return ((vpit->count>>8) & 0xFF); + } else { + /* Unlatched Count Read */ + VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: unlatched read"); + pit_cal_count(vpit); + if(!(vpit->read_state & 0x1)) { + /* Read Least Significant Byte */ + if(vpit->read_state==LSByte_multiple) { + vpit->read_state=MSByte_multiple; + } + return (vpit->count & 0xFF); + } else { + /* Read Most Significant Byte */ + if(vpit->read_state==MSByte_multiple) { + vpit->read_state=LSByte_multiple; + } + return ((vpit->count>>8) & 0xFF); + } + } +} + +/* vmx_io_assist light-weight version, specific to PIT DM */ +static void resume_pit_io(ioreq_t *p) +{ + execution_context_t *ec = get_execution_context(); + unsigned long old_eax = ec->eax; + p->state = STATE_INVALID; + + switch(p->size) { + case 1: + ec->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff); + break; + case 2: + ec->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff); + break; + case 4: + ec->eax = (p->u.data & 0xffffffff); + break; + default: + BUG(); + } +} + +/* the intercept action for PIT DM retval:0--not handled; 1--handled */ +int intercept_pit_io(ioreq_t *p) +{ + struct exec_domain *d = current; + struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit); + + if (p->size != 1 || + p->pdata_valid || + p->port_mm) + return 0; + + if (p->addr == 0x43 && + p->dir == 0 && /* write */ + ((p->u.data >> 4) & 0x3) == 0 && /* latch command */ + ((p->u.data >> 6) & 0x3) == (vpit->channel)) {/* right channel */ + pit_latch_io(vpit); + return 1; + } + + if (p->addr == (0x40 + vpit->channel) && + p->dir == 1) { /* read */ + p->u.data = pit_read_io(vpit); + resume_pit_io(p); + return 1; + } + + return 0; +} + +/* hooks function for the PIT initialization response iopacket */ +static void pit_timer_fn(unsigned long data) +{ + struct vmx_virpit_t *vpit = (struct vmx_virpit_t*)data; + + /* rearm itself */ + vpit->pit_timer.expires = NOW() + MILLISECS(vpit->period); + + /*set the pending intr bit in shared page, send evtchn notification to myself*/ + if (test_and_set_bit(vpit->vector, vpit->intr_bitmap)) + vpit->pending_intr_nr++; /* if originaly set, then count the pending intr */ + + add_ac_timer(&(vpit->pit_timer)); +} + + +/* Only some PIT operations such as load init counter need a hypervisor hook. + * leave many other operations in user space DM + */ +void vmx_hooks_assist(struct exec_domain *d) +{ + vcpu_iodata_t *vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va; + ioreq_t *p = &vio->vp_ioreq; + unsigned long *intr = &(vio->vp_intr[0]); + struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit); + int rw_mode; + + if (p->state == STATE_IORESP_HOOK) { /*load init count*/ + vpit->init_val = (p->u.data & 0xFFFF) ; /* frequency(ms) of pit */ + vpit->period = (vpit->init_val) * 1000 / PIT_FREQ; /* frequency(ms) of pit */ + vpit->vector = ((p->u.data >> 16) & 0xFF); + vpit->channel = ((p->u.data >> 24) & 0x3); + + vpit->count_LSB_latched = 0; + vpit->count_MSB_latched = 0; + + rw_mode = ((p->u.data >> 26) & 0x3); + switch(rw_mode) { + case 0x1: + vpit->read_state=LSByte; + break; + case 0x2: + vpit->read_state=MSByte; + break; + case 0x3: + vpit->read_state=LSByte_multiple; + break; + default: + printk("VMX_PIT:wrong PIT rw_mode!\n"); + break; + } + + vpit->intr_bitmap = intr; + + /* set up the actimer */ + init_ac_timer(&(vpit->pit_timer)); + vpit->pit_timer.cpu = 0; /*FIXME: change for SMP */ + vpit->pit_timer.data = (unsigned long)vpit; + vpit->pit_timer.function = pit_timer_fn; + pit_timer_fn((unsigned long)vpit); /* timer seed */ + + /*restore the state*/ + p->state = STATE_IORESP_READY; + + /* register handler to intercept the PIT io when vm_exit */ + register_io_handler(0x40, 4, intercept_pit_io); + } + +} diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index 440b51d5b4..3241ada865 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_VMX @@ -197,6 +198,11 @@ void vmx_io_assist(struct exec_domain *ed) domain_crash(); } p = &vio->vp_ioreq; + + if (p->state == STATE_IORESP_HOOK){ + vmx_hooks_assist(ed); + } + /* clear IO wait VMX flag */ if (test_bit(ARCH_VMX_IO_WAIT, &ed->arch.arch_vmx.flags)) { if (p->state != STATE_IORESP_READY) { @@ -337,6 +343,7 @@ void vmx_intr_assist(struct exec_domain *d) { int highest_vector = find_highest_pending_irq(d); unsigned long intr_fields, eflags; + struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit); if (highest_vector == -1) return; @@ -355,12 +362,19 @@ void vmx_intr_assist(struct exec_domain *d) return; } - clear_highest_bit(d, highest_vector); + if (vpit->pending_intr_nr && highest_vector == vpit->vector) + vpit->pending_intr_nr--; + else + clear_highest_bit(d, highest_vector); + intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector); __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields); __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); + if (highest_vector == vpit->vector) + vpit->inject_point = NOW(); + return; } diff --git a/xen/include/asm-x86/vmx_intercept.h b/xen/include/asm-x86/vmx_intercept.h new file mode 100644 index 0000000000..54f118ce39 --- /dev/null +++ b/xen/include/asm-x86/vmx_intercept.h @@ -0,0 +1,31 @@ + +#ifndef _VMX_INTERCEPT_H +#define _VMX_INTERCEPT_H + +#include +#include +#include +#include +#include +#include + + +#define MAX_IO_HANDLER 6 + +typedef int (*intercept_action_t)(ioreq_t*); + +struct vmx_handler_t { + int num_slot; + struct { + unsigned long addr; + unsigned long offset; + intercept_action_t action; + } hdl_list[MAX_IO_HANDLER]; +}; + +/* global io interception point in HV */ +extern int vmx_io_intercept(ioreq_t*); +extern int register_io_handler(unsigned long, unsigned long, intercept_action_t); + + +#endif /* _VMX_INTERCEPT_H */ diff --git a/xen/include/asm-x86/vmx_platform.h b/xen/include/asm-x86/vmx_platform.h index 4557e5d083..63cb74d90f 100644 --- a/xen/include/asm-x86/vmx_platform.h +++ b/xen/include/asm-x86/vmx_platform.h @@ -21,6 +21,8 @@ #include #include +#include +#include #define MAX_OPERAND_NUM 3 #define I_NAME_LEN 16 @@ -79,6 +81,8 @@ struct mi_per_cpu_info struct virutal_platform_def { unsigned long *real_mode_data; /* E820, etc. */ unsigned long shared_page_va; + struct vmx_virpit_t vmx_pit; + struct vmx_handler_t vmx_handler; struct mi_per_cpu_info mpci; /* MMIO */ }; diff --git a/xen/include/asm-x86/vmx_virpit.h b/xen/include/asm-x86/vmx_virpit.h new file mode 100644 index 0000000000..91a08c204d --- /dev/null +++ b/xen/include/asm-x86/vmx_virpit.h @@ -0,0 +1,81 @@ + +#ifndef _VMX_VIRPIT_H +#define _VMX_VIRPIT_H +#include +#include +#include +#include +#include +#include +#include + +#define PIT_FREQ 1193181 + +#define LSByte 0 +#define MSByte 1 +#define LSByte_multiple 2 +#define MSByte_multiple 3 + +struct vmx_virpit_t { + /* for simulation of counter 0 in mode 2*/ + int vector; /* the pit irq vector */ + unsigned int period; /* the frequency. e.g. 10ms*/ + unsigned int channel; /* the pit channel, counter 0~2 */ + unsigned long *intr_bitmap; + unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ + unsigned long long inject_point; /* the time inject virt intr */ + struct ac_timer pit_timer; /* periodic timer for mode 2*/ + + /* virtual PIT state for handle related I/O */ + int read_state; + int count_LSB_latched; + int count_MSB_latched; + + unsigned int count; /* the 16 bit channel count */ + unsigned int init_val; /* the init value for the counter */ + +} ; + +/* to hook the ioreq packet to get the PIT initializaiton info */ +extern void vmx_hooks_assist(struct exec_domain *d); + +#endif /* _VMX_VIRPIT_H_ */ + +#ifndef _VMX_VIRPIT_H +#define _VMX_VIRPIT_H +#include +#include +#include +#include +#include +#include +#include + +#define PIT_FREQ 1193181 + +#define LSByte 0 +#define MSByte 1 +#define LSByte_multiple 2 +#define MSByte_multiple 3 + +struct vmx_virpit_t { + /* for simulation of counter 0 in mode 2*/ + int vector; /* the pit irq vector */ + unsigned int period; /* the frequency. e.g. 10ms*/ + unsigned int channel; /* the pit channel, counter 0~2 */ + unsigned long *intr_bitmap; + unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ + unsigned long long inject_point; /* the time inject virt intr */ + struct ac_timer pit_timer; /* periodic timer for mode 2*/ + + /* virtual PIT state for handle related I/O */ + int read_state; + int count_LSB_latched; + int count_MSB_latched; + + unsigned int count; /* the 16 bit channel count */ + unsigned int init_val; /* the init value for the counter */ + +} ; + +#endif /* _VMX_VIRPIT_H_ */ diff --git a/xen/include/public/io/ioreq.h b/xen/include/public/io/ioreq.h index ac47cd9ec5..2f01d88385 100644 --- a/xen/include/public/io/ioreq.h +++ b/xen/include/public/io/ioreq.h @@ -27,6 +27,7 @@ #define STATE_IOREQ_READY 1 #define STATE_IOREQ_INPROCESS 2 #define STATE_IORESP_READY 3 +#define STATE_IORESP_HOOK 4 #define IOPACKET_PORT 2 -- 2.30.2